
#define DEBUG
#include "tracker.h"

struct node *head=NULL; 
static int Test=0;

//struct file_part *fhead=NULL;

/******************************Functions definations**************************************/

/* This function just makes Initial 1st time (peer_count = 1), DS popuate for each file, 
*  remaining all updates for each part are handled by update function 
*/

void append_file_part(struct node **new1, char *fname, int seed_id,int part_number, int myport, char IP_addr[IPv4_SIZE]) // 6 parameters passed
{
    struct node *temp;
    struct file_part *new_temp, *r;

    //char * f_name;
    char f_name[BUF_SIZE];
    int peer_count = 0;
    temp = *new1 ;
	
   // f_name = temp->value;

    strcpy(f_name,temp->value);
	//printf("\n Inside Append file part with file name f_name: %s , and fname = %s\n\n ",f_name, fname);fflush(stdout);  

   
	

   if ( temp->next ==NULL){

	peer_count = 0;	  
	if( temp->node_part == NULL)
	{       
               	new_temp = (struct file_part *)malloc ( sizeof ( struct file_part) ) ;

		        new_temp-> next = NULL;                                                 
		        new_temp-> part_num = part_number;

                new_temp-> seeder_list[peer_count].seeder_id = seed_id;
                new_temp-> seeder_list[peer_count].sd_sin.sin_port = htons(myport) ; // ????
		        inet_pton(AF_INET,IP_addr,&(new_temp-> seeder_list[peer_count].sd_sin.sin_addr));
                new_temp-> seeder_list[peer_count].sd_sin.sin_family = AF_INET ;

                /*
  			        Few more fields to put.. like dwld status n all .......
     		    */


		       temp->node_part = new_temp;
		       //printf("\n Inside append_file_part : %s , of part number %d , seeder_IP %s and Port ", temp->value, new_temp-> part_num,myport);
     	}

	else
	{
		new_temp = temp->node_part ;
		while ( new_temp -> next != NULL ) 
		new_temp = new_temp -> next ;

		r = (struct file_part *)malloc ( sizeof ( struct file_part ) ) ;
		r-> next = NULL;
		r-> part_num = part_number;
                r-> seeder_list[peer_count].seeder_id = seed_id;
                r-> seeder_list[peer_count].sd_sin.sin_port = htons(myport) ;
                inet_pton(AF_INET,IP_addr,&(r-> seeder_list[peer_count].sd_sin.sin_addr));
                r-> seeder_list[peer_count].sd_sin.sin_family = AF_INET ;	

                 /*
  			Few more fields to put.. like dwld status n all .......
     		*/

		inet_ntop(AF_INET,&(r-> seeder_list[peer_count].sd_sin.sin_addr),IP_addr,IPv4_SIZE); // presentation					 		                           
		new_temp-> next = r;
		printf("\n Inside append_file_part : \t%s, \t%d , \t%s, \t%d", temp->value, r-> part_num, IP_addr, ntohs(r-> seeder_list[peer_count].sd_sin.sin_port));

	}
  }

 else  {
  while ( temp -> next != NULL ) 
   temp = temp->next;

  peer_count = 0;	  
	if( temp->node_part == NULL)
	{       
               	new_temp = (struct file_part *)malloc ( sizeof ( struct file_part) ) ;

		        new_temp-> next = NULL;                                                 
		        new_temp-> part_num = part_number;

                new_temp-> seeder_list[peer_count].seeder_id = seed_id;
                new_temp-> seeder_list[peer_count].sd_sin.sin_port = htons(myport) ; // ????
		        inet_pton(AF_INET,IP_addr,&(new_temp-> seeder_list[peer_count].sd_sin.sin_addr));
                new_temp-> seeder_list[peer_count].sd_sin.sin_family = AF_INET ;

                /*
  			        Few more fields to put.. like dwld status n all .......
     		    */


		       temp->node_part = new_temp;
		       //printf("\n Inside append_file_part : %s , of part number %d , seeder_IP %s and Port ", temp->value, new_temp-> part_num,myport);
     	}

	else
	{
		new_temp = temp->node_part ;
		while ( new_temp -> next != NULL ) 
		new_temp = new_temp -> next ;

		r = (struct file_part *)malloc ( sizeof ( struct file_part ) ) ;
		r-> next = NULL;
		r-> part_num = part_number;
                r-> seeder_list[peer_count].seeder_id = seed_id;
                r-> seeder_list[peer_count].sd_sin.sin_port = htons(myport) ;
                inet_pton(AF_INET,IP_addr,&(r-> seeder_list[peer_count].sd_sin.sin_addr));
                r-> seeder_list[peer_count].sd_sin.sin_family = AF_INET ;	

                 /*
  			Few more fields to put.. like dwld status n all .......
     		*/

		inet_ntop(AF_INET,&(r-> seeder_list[peer_count].sd_sin.sin_addr),IP_addr,IPv4_SIZE); // presentation					 		                           
		new_temp-> next = r;
		printf("\n Inside append_file_part : \t%s, \t%d , \t%s, \t%d", temp->value, r-> part_num, IP_addr, ntohs(r-> seeder_list[peer_count].sd_sin.sin_port));

	}

  

   

   }

}

/****************** append function *************************************************/


void append_list ( struct node ** new2, char * name )
{
struct node *temp, *r ;
   static int i=1;
	if ( *new2 == NULL )  // if the list is empty, create first node
    {
		printf("\n There is no file present , at start");
		fflush(stdout);
        temp = (struct node *)malloc ( sizeof ( struct node) ) ;
	    strcpy(temp->value,name);  //temp -> value = name ;
        temp -> next = NULL ;
        temp -> node_part = NULL;
        *new2 = temp ;
		printf("\n Inside append_list ( 1st Node ): %s ", temp->value);
		fflush(stdout);
		i++;
    }
    else
    {   		  
	temp = *new2 ;

	while ( temp->next!= NULL ) // go to last node 
	{	
		temp = temp -> next ;
		printf("\nIncrementing node in appendix list............ %d",i);
       fflush(stdout);
		i++;				
	}
	//printf("\n Appending ith %d at next location current location : %s ", i,temp->value);
	//fflush(stdout);
	r = (struct node *)malloc ( sizeof ( struct node ) ) ; // add node at the end 
	strcpy(r->value, name ); // r -> value = name ;
	r -> next = NULL ;
	r -> node_part = NULL;
	temp->next = r ;
	printf("\n Inside append_list (other parts).........................: %s ", r->value);
	fflush(stdout);
	

    } 
}

/********************* Update function **************************/

void Update ( struct node **new1, char *fname, char * protocol, int p_id, int part_number, int myport, char IP_addr[IPv4_SIZE]) // 7 parameters
{
    struct node *temp;
    struct file_part *new_temp, *r;
    char f_name[BUF_SIZE], protocol_code;
    int i= 0;

    int peer_count ;  
    temp = *new1 ;

    protocol_code = protocol;
	
	
    strcpy(f_name,temp->value) ;//f_name = temp->value;

	printf("\n Inside update function .. \n");




printf("\n f_value %s, temp->value %s, fname %s \n", f_name, temp->value, fname); fflush(stdout);
    printf("\n Planning for strcmp "); fflush(stdout);

	while ( strcmp((char *)fname, (const char*)f_name)!= 0)
	{
		temp = temp->next;
		strcpy(f_name,temp->value);  //  f_name = temp->value;
                printf("\n inside while ....");
               
		if(temp->next == NULL && (strcmp((char *)fname, (const char*)f_name) != 0 ))
		{
			printf("\n Sorry ! File not present in the file_list. Needs to be added ");
			//getch();
			exit(1);
		}
   	} 

  

	printf("\n Inside update f_name is matched temp->value = %s",temp->value); fflush(stdout);

   new_temp = temp->node_part ;
   printf("\n Debug -1\n"); fflush(stdout);
   if (part_number != 1)
   {  
    
   	for ( i = 1 ; i < part_number ; i++ )
	new_temp = new_temp -> next ;
     
   }
  
   printf("\n new_temp->part_num = %d,  part_number  = %d", new_temp->part_num, part_number); fflush(stdout); 
   printf("\n .... Debug -2\n"); fflush(stdout);



   /* new_temp = temp->node_part ;

	for ( i = 1 ; i < part_number ; i++ )
	new_temp = new_temp -> next ;

	if ( new_temp == NULL )
	{
		printf ( "\nThere are less than %d elements in list", part_number ) ;
		return ;
	}
    
    printf("\n.... new_temp->part_num = %d, part_number = %d ............\n ", new_temp->part_num, part_number ); */


	if ( new_temp->part_num == part_number)
	{        
            
		
         if ( protocol_code == 0x01) // seeder update
	     {
                for (peer_count=0;peer_count< MAX_PEERS;) // Reach 
                {
                  printf("\n peer id is %d", new_temp->seeder_list[peer_count].seeder_id); fflush(stdout);
		          if(new_temp->seeder_list[peer_count].seeder_id == 0) ; // Initialise somewhere , this array as null. = {0};
                  peer_count++;
                  break ; 
	            }
		
                printf("\n update .. protocol 0x01... \n peer count is %d \n", peer_count);  fflush(stdout);
                new_temp-> seeder_list[peer_count].seeder_id = p_id;
		        new_temp-> seeder_list[peer_count].sd_sin.sin_port = htons(myport) ; 
                //new_temp-> seeder_list[peer_count].sd_sin.sin_addr.s_addr = IP_addr ;
                inet_pton(AF_INET,IP_addr,&(new_temp-> seeder_list[peer_count].sd_sin.sin_addr));
                new_temp-> seeder_list[peer_count].sd_sin.sin_family = AF_INET ;
	     }

        else  // leecher update
	    {
                 for (peer_count=0;peer_count< MAX_PEERS;peer_count++) // Reach 
                 {
	            	   if(new_temp->leecher_list[peer_count].leecher_id == NULL ); // Initialise somewhere , this array as null. = {0};
                       break ; 
	             }
                 new_temp-> leecher_list[peer_count].leecher_id = p_id;
		          new_temp-> leecher_list[peer_count].lc_sin.sin_port = htons(myport) ; // ???? or just myport;
                 //new_temp-> leecher_list[peer_count].lc_sin.sin_addr.s_addr = IP_addr ;
                 inet_pton(AF_INET,IP_addr,&(new_temp-> leecher_list[peer_count].lc_sin.sin_addr));
                 new_temp-> leecher_list[peer_count].lc_sin.sin_family = AF_INET ;
	     }
          
	}

       //printf("\n\n Percentage downloaded for part number %d is %f ",part_number, new_temp->percent_downloaded);
       printf("\n\n Its peer id is : %d \n\n ",new_temp->seeder_list[peer_count].seeder_id);

}

void print_list(struct node *head)
{
	struct node * temp=head;
    struct file_part * horizontal;
	int i=0;

	char pipbuff[IPv4_SIZE]={0};

	if (temp != NULL)
    { 
    	//temp->value;
    	//printf("\n Head value %s",temp->value);
	while(temp!=NULL)
	{
		printf("\n ***********  Head value %s*******************",temp->value);
		fflush(stdout);
		if(temp->node_part==NULL)
			printf("\n The horizontal node is NULL");
     if ( temp->node_part != NULL)
		{
        	horizontal = temp->node_part;
	  		while ( horizontal != NULL)
        	{ 
 
		        printf("\n***The Data in part list of file is:***");
    	        printf("\nPart number: %d",horizontal->part_num);
       
    		    printf("\n Seeder Info:\n");
    		    for(i=0;i<MAX_SEEDS;i++)
        		{
            		//************************************* Change the formatting specifiers according to length
            		printf("\tID:%5d", horizontal->seeder_list[i].seeder_id);
            		inet_ntop(AF_INET, &(horizontal->seeder_list[i].sd_sin.sin_addr), pipbuff, IPv4_SIZE);
            		printf("  Seeder ip is :%16s",pipbuff);    
            		memset(&pipbuff,0,IPv4_SIZE);
            		printf(" | ");
            		if((i%3)==2)
					{
            			printf("\n");
            		}
        		}
        		printf("\n Leecher Info:\n");
		        for(i=0;i<MAX_LEECHES;i++)
    		    {
        		    printf("\tID:%5d", horizontal->leecher_list[i].leecher_id);
            		inet_ntop(AF_INET, &(horizontal->leecher_list[i].lc_sin.sin_addr), pipbuff, IPv4_SIZE);
            		printf("  Leecher ip is :%16s",pipbuff);    
            		memset(&pipbuff,0,IPv4_SIZE);
           			printf(" | ");
            		if((i%3)==2)
					{
            			printf("\n");
           		 	}
        		}
        
        		horizontal=horizontal->next; // go to next horizontal node (FILE pART)
        		printf("************\n");
    		} //end of while
    
	     }
	
		temp=temp->next;
		printf("\n *************.................File Ended ..........*******************************************\n");
		fflush(stdout);		
		}//end of while vertical
	}
}


/************************************ Read_DS_and_send *******************************/

char* Read_DS ( struct node **new1, char *fname, int seq_no, int part_number )
{
    struct node *temp;
    struct file_part *new_temp, *r;
    //char * f_name;
    char f_name[BUF_SIZE];
    int i= 0;
    char send_buffer[512];
    char token3[100];
    int peer_id, port_no;
    char IP_addr[IPv4_SIZE];
    char* reply_protocol = "0x04";

    char send_this[512]= {0};
    char s_buff[64];

    int ack_no = seq_no +1;
    char ss_buff[100] = "FNF";
    temp = *new1 ;

   // printf("\n\n .... ack_no... = %d, fname = %s ", ack_no, fname);
    printf("\n\n **************** PART NUMBER = %d *************************", part_number);
	
    printf("\n Inside Read DS .... \n"); fflush(stdout);
    strcpy(f_name, temp->value); // f_name = temp->value;
    
	printf("\n f_value %s, temp->value %s, fname %s \n", f_name, temp->value, fname); fflush(stdout);
    printf("\n Planning for strcmp "); fflush(stdout);

	while ( strcmp((char *)fname, (const char*)f_name)!= 0)
	{
		temp = temp->next;
		strcpy(f_name,temp->value);  //  f_name = temp->value;
                printf("\n inside while ....");
               
		if(temp->next == NULL && (strcmp((char *)fname, (const char*)f_name) != 0 ))
		{
			printf("\n Sorry ! File not present in the file_list. Needs to be added ");
			
            
			sprintf(send_buffer,"%s",ss_buff);  // IF file not found, send the ERROR CODE " FNF " to tracker .
           
			printf("\n\n send buffer is : %s\n", send_buffer);
            return send_buffer; 
			//exit(1);
		}
   	} 

    

   new_temp = temp->node_part ;
   printf("\n Debug -1\n"); fflush(stdout);
   if (part_number != 1)
   {  
    
   	for ( i = 1 ; i < part_number ; i++ )
	new_temp = new_temp -> next ;
     
   }
  
  
      printf("\n Debug -3 ............\n"); //fflush(stdout); 
      printf("\n new_temp->part_num = %d,  part_number  = %d", new_temp->part_num, part_number); fflush(stdout); 

     strcpy((char *)send_this,(const char *)"");
     printf("\n Debug -4\n"); fflush(stdout); 


	if ( new_temp->part_num == part_number)  // Need to read always seeder info .. reqd for seeding.
	{   
       printf("\n Debug -5\n"); fflush(stdout); 
      for( i=0;i< 10 ;i++)
      {
           if(new_temp->seeder_list[i].seeder_id == 0)
           { 
             break;
           }

	        printf("\n Peer_id read from DS is %d",new_temp->seeder_list[i].seeder_id);

	        peer_id = new_temp->seeder_list[i].seeder_id;
            port_no = ntohs(new_temp->seeder_list[i].sd_sin.sin_port);                      
	        // IP_addr = new_temp->seeder_list[i].sd_sin.sin_addr.s_addr;                         
           inet_ntop(AF_INET,&(new_temp->seeder_list[i].sd_sin.sin_addr),IP_addr,IPv4_SIZE); // presentation 

  printf("\n\n Peer id [%d] = %d, port_no [%d] = %d , IP [%d] = %s ", i, new_temp->seeder_list[i].seeder_id, i, ntohs(new_temp->seeder_list[i].sd_sin.sin_port), i, IP_addr); 				
          fflush(stdout);
         sprintf(s_buff,"%d:%s:%d,",new_temp->seeder_list[i].seeder_id,IP_addr,ntohs(new_temp->seeder_list[i].sd_sin.sin_port));
		 strcat((char *)send_this,(const char *) s_buff);
         
		
	  }
                     
	}
    
    printf("\n\n .... Send_this  = %s ", send_this);
     
	sprintf(send_buffer,"%s$%d$%s$%d$%s",reply_protocol,ack_no,fname,part_number,send_this); // is protocol code %s or %u or %d ?? also IP YES ??
                 
                                         // sprintf(send_buffer,"%s$%d$%s$%d",reply_protocol,ack_no,fname,peer_id); // FILL MORE ....

         printf("\n\n send buffer is : %s\n", send_buffer);
         return send_buffer; 

}


int main(void)
{
	int alen,t;
        char IP_addr[IPv4_SIZE]; 

        pthread_t	new_thread[NUMBER_OF_THREADS];
	pthread_attr_t	thread_attr;

		
	/******************** Proxy_Server data structures *****************/
	
	struct sockaddr_in tracker_sin;	/* Proxy server endpoint   */
	struct sockaddr_in client_sin;	    	/* an SMTP Client endpoint */
	struct servent	*tracker_pse;	        /* pointer to port, currently not used in code */
	int	msocket, ssocket;		/* socket descriptor and socket type */

	/********************************************************************/

	
	memset(&tracker_sin,0,sizeof(tracker_sin) );
	memset(&client_sin,0,sizeof(client_sin) );
	printf("\n Starting my Sparta Torrent Tracker ...\n");
	
				
	/************************P_Server side ******************************************/

      	tracker_sin.sin_family = AF_INET;
	tracker_sin.sin_addr.s_addr = INADDR_ANY;
        tracker_sin.sin_port = htons(TRACKER_PORT);
	
	
	/*Create TCP master Socket for Proxy Server*/
	msocket = socket(PF_INET, SOCK_STREAM,0);
	if (msocket < 0)
		printf("\n Cannot create the socket ");

       /* Bind the master socket */
	if (bind(msocket, (struct sockaddr *)&tracker_sin, sizeof(tracker_sin)) < 0)
		printf("\n ERROR ! Cannot bind the socket ");

    	if (listen(msocket, 3) < 0)
		printf("\n ERROR ! Cannot listen the socket ");
		
	while (1) 
	{
		//printf(" \n Inside while: Waiting for connections\n");
		printf(" \n Creating New Thread ..\n");
		
	       (void) pthread_attr_init(&thread_attr);
	       (void) pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
                
	        for(t=0;t<NUMBER_OF_THREADS;t++) 
	        {
		  alen = sizeof(client_sin);
                  printf("\n Waiting at accept call ....... \n\n");
		  fflush(stdout);
		  ssocket = accept(msocket, (struct sockaddr *)&client_sin, &alen);
                  
		  printf("\n Socket accepted .... \n\n ");
		  fflush(stdout);
                
		  if (ssocket < 0)
			{
				if (errno == EINTR)
					continue;
				printf("accept: %s\n", strerror(errno));
			}
                

              	   thread_data_array[t].ssocket = ssocket;
                 //  thread_data_array[t].seeder_list[t].sd_sin.sin_port = client_sin.sin_port ;
		   thread_data_array[t].client_sin.sin_addr.s_addr = client_sin.sin_addr.s_addr ; 
                   thread_data_array[t].client_sin.sin_family = AF_INET ;

                  #ifdef DEBUG
                    inet_ntop(AF_INET,&(thread_data_array[t].client_sin.sin_addr),IP_addr,IPv4_SIZE); // presentation
                    printf("\n its IP is : %s ", IP_addr);
                    fflush(stdout);
                  #endif
              if(head!=NULL)
				{
					printf("\n Very Initial Value of Head is %s",head->value);					
					fflush(stdout);
				}    
                   if (pthread_create(&new_thread[t], &thread_attr,communicate,(void *)&thread_data_array[t]) < 0)
		   printf("\n ERROR ! Cannot Create new thread. ");
                   
                   printf("\n Before passing to function ....  ssocket is : %d, ... %d", thread_data_array[t].ssocket, ssocket);
			        
               } 

	}   // while end
}
 
void * communicate(void * thread_arguement)
{
 
   int r, i ,buff_len;
  char buff[BUF_SIZE]={0}, cp[BUF_SIZE]={0};
  char *filename;
  //char filename[BUF_SIZE];
  //unsigned char * protocol_feild;
  //unsigned char protocol_feild[BUF_SIZE];
  unsigned char *protocol_feild;
  unsigned int protocol=9;


  const char delimiter[] = "$";
  struct sockaddr_in cli_sin; 

  char *no_of_parts, *peer_id, *port_num, *part_no_available, *seeder_id, *leecher_id , *seq_no, *send_buffer;

  //char no_of_parts[BUF_SIZE], peer_id[BUF_SIZE], port_num[BUF_SIZE], part_no_available[BUF_SIZE], seeder_id[BUF_SIZE], leecher_id[BUF_SIZE] , seq_no[BUF_SIZE],    send_buffer[BUF_SIZE];

  int total_parts, seed_id, port_here, part_available, s_id, l_id, sequence_no ;
 
  struct thread_data *threaddata;
	
  char IP_address[IPv4_SIZE]; 
  int bufflen=BUF_SIZE;	

  int new_socket;
  threaddata = (struct thread_data*)thread_arguement;
  new_socket=threaddata->ssocket;
	
  cli_sin.sin_addr.s_addr=threaddata->client_sin.sin_addr.s_addr;        
   //memcpy(&cli_sin,threaddata->client_sin,sizeof(threaddata->client_sin.sin_addr));

  printf("\n Inside communicate function ");
  printf("\n Inside function ....  ssocket is : %d", new_socket);
  fflush(stdout);
  if(Test>0)
				{
					printf("\n The initial Value of Head is %s",head->value);					
					fflush(stdout);
				}    

  memset(&buff,0,BUF_SIZE);
 inet_ntop(AF_INET,&(cli_sin.sin_addr),IP_address,IPv4_SIZE); // presentation

#ifdef DEBUG
  printf("\n IP, passed inside function is : %s ", IP_address);
  fflush(stdout);
#endif
    
  
   /* start reading buffer for Communication Protocol */
  // printf("\n Now reading the buffer ......");
  // fflush(stdout);

   r = read(new_socket,buff, bufflen-1);
   if(r<0){
	printf("\n Error in Reading from Peers");
	}
 //  printf("\n Read data ... r is:%d",r);
 //	fflush(stdout);
   buff[r]='\0';
 //  printf("\nReceived Msg :%s",buff);
//	printf("\n Received Buffer , Now copying input to other buffer => tokenizing..");    
//	fflush(stdout);
	printf("\n buffer is %s", buff);
        fflush(stdout);

   strcpy((char*)cp,(const char *)buff);
   printf("\n before protocol.......... : %s",cp);
   fflush(stdout);

   protocol_feild = strtok(buff,delimiter);
   //  strncpy(&protocol, protocol_feild, 1);
   protocol = atoi(protocol_feild);

    //protocol = strtok(buff,delimiter);
	//printf("\n Buffer %s copied.. received token: %x",buff,protocol);    
	//fflush(stdout);

   switch (protocol)
   {
        case 0x00: // 1st time populate DS. Msg format :  [ protocol $ filename $ no_of_parts $ peer_id $ port_num ] // Always by Seeder
                   // No Reply send from tracker
 #ifdef DEBUG
		    printf("\n Inside protocol 0x00.....................................\n\n");
		   fflush(stdout);
#endif

                   filename = strtok(NULL, delimiter);
                   no_of_parts = strtok(NULL, delimiter);
                   //total_parts = atoi(no_of_parts);
                   sscanf (no_of_parts, "%d", &total_parts); 
                
                   peer_id = strtok(NULL, delimiter);
                   sscanf (peer_id, "%d", &seed_id); 

		           port_num = strtok(NULL, delimiter);
                   sscanf (port_num, "%d", &port_here); 
				  if(Test>0)
				   {
					printf("\n The Start Value of Head(before append) is %s",head->value);					
					fflush(stdout);
				   }  
    
                   printf("\n................ Before append_list ...............\n"); fflush(stdout);         
				   append_list(&head,filename);
                   printf("\n................ After append_list ...............\n"); fflush(stdout);
    
                  	printf("\n The Start Value of Head is %s",head->value);					
					Test++;
					fflush(stdout);     
              
				for(i=1 ;i <= total_parts;i++)
         		   {
		 			append_file_part( &head, filename, seed_id, i , port_here, IP_address); // IP & port need to taken from struct client_sin ( 6 parameter pass)
				   }	
				printf("\n The Start Value of Head is................................ after append had been called %s",head->value);					
				fflush(stdout);	
	
			    print_list(head);  
			    printf("\n The Start Value of Head is %s",head->value);					
				fflush(stdout);                 
 			    break;



        case 0x01: // Seeder Update. Msg format : [ protocol $ filename $ part_no_available $ seeder_id $ port_num ]
		           // No Reply send from tracker

 #ifdef DEBUG
		    printf("\n Inside protocol 0x01");
		    fflush(stdout);
#endif
                   filename = strtok(NULL, delimiter);
                   part_no_available = strtok(NULL, delimiter);
                   sscanf (part_no_available, "%d", &part_available); 
 
                   seeder_id = strtok(NULL, delimiter);
                   sscanf (seeder_id, "%d", &s_id); 

                   port_num = strtok(NULL, delimiter);
                   sscanf (port_num, "%d", &port_here); 
                   printf("\n ........................... Before update called..................\n");
                   
		           Update( &head, filename, protocol, s_id, part_available, port_here, IP_address); //  7 parameters passed
			       //break;
                   printf("\n ........................... After update called..................\n");
                   print_list(head);  
                   break;
                 
        case 0x02: // Get Update for that file part. Msg format : [ protocol $ seq_num $ filename $ part_num ]
                   // No reply send from tracker

/******************************************************************************************************************************************
		
C) 0x02 get info on file part request (This is request from leecher, requesting the latest seeder info on specific part)

(Assuming 2 seeders are present)

		2$seq_no$filename$part_num$
		
		REPLY from tracker to leecher: 2$seq_no$filename$part_num$peer_id:seeder1IPaddr:port,peer_id:seeder2IPaddr:port$
		
		ACTION on tracker : read fields for file part from DS and send reply.
******************************************************************************************************************************************/

   
#ifdef DEBUG
		    printf("\n Inside protocol 0x02.. actually");
		   fflush(stdout);
#endif
                   seq_no =  strtok(NULL, delimiter);                 
                   sscanf (seq_no, "%d", &sequence_no); 

		           filename = strtok(NULL, delimiter);

                   part_no_available = strtok(NULL, delimiter);
                   sscanf (part_no_available, "%d", &part_available); 
 
                /*
				   leecher_id = strtok(NULL, delimiter);
                   sscanf (leecher_id, "%d", &l_id); 

		           port_num = strtok(NULL, delimiter);
                   sscanf (port_num, "%d", &port_here); */
                 
                  // Update( &head, filename, protocol, s_id, part_available, port_here, IP_address); //  7 parameters passed

				  send_buffer = Read_DS(&head,filename, sequence_no,part_available); 
    
                  r = strlen(send_buffer);
	              printf("\n Size of buffer to be send is : %d",r);

	               if ( write(new_socket,send_buffer,r)<0)
                     {
		              printf("\n Error ! Wriritng to peer Server socket failed ");
                      break; 
                     }

                   break;


        case 0x03: // Reterive info request. Msg format : [ protocol $ seq_no $ filename $ no_of_parts ]  // Always by leecher

        // Reply from the tracker. Reply format : [ protocol $ ack_no [seq_no + 1] $ filename $ part_num $ seeder_id-1:port_no-1:IP-1, seeder_id-2:port_no-2:IP-2,seeder_id-3:port_no-3:IP-3, ..... ] here ip n port will be read from DS. This reply is send for each part ( its for loop)


#ifdef DEBUG
		   printf("\n Inside protocol 0x03");
		   fflush(stdout);
#endif
                  seq_no = strtok(NULL, delimiter);
                  sscanf (seq_no, "%d", &sequence_no);
                  //printf("\n debug -1 ... %d",sequence_no); fflush(stdout);

		          filename = strtok(NULL, delimiter);
                  //printf("\n debug -1 ... %s",filename); fflush(stdout);

                  no_of_parts = strtok(NULL, delimiter);
		          sscanf (no_of_parts, "%d", &total_parts);
                  printf("\n Before calling Read  ...     total parts %d", total_parts); fflush(stdout);

                  for(i=1;i<=total_parts;i++)
		          {
                     //printf("\n debug -3"); fflush(stdout);
                     send_buffer = Read_DS(&head,filename, sequence_no,i); 

                    //send_buffer='\0';

                   r = strlen(send_buffer);
	               printf("\n Size of buffer to be send is : %d",r);

	               if ( write(new_socket,send_buffer,r)<0)
                     {
		              printf("\n Error ! Wriritng to peer Server socket failed ");
                      break; 
                     }
		          }

           }// Switch ends


	printf("\n\n Exiting Thread Now ....... \n\n");
        fflush(stdout);
	pthread_exit(NULL);
}

